
#include "stdafx.h"
#include "myutil.h"

void myutil::pause(int n)
{
	cout << "-" << n << "- Press any key to continue... ";
	getchar();
}

int myutil::readFile(const char * path, string & res_str)
{
	res_str.clear();
	FILE * f = fopen(path, "rb");

	if(f == NULL)
	{
		printf("Can not open file.\n");
		return 1;
	}

	const int BUF_SIZE = 1024 * 128;
	char buf[BUF_SIZE];
	while(true)
	{
		int read_num = fread(buf, sizeof(char), BUF_SIZE, f);
		if(read_num <= 0)
		{
			break;
		}
		res_str.append(buf, read_num);
	}
	fclose(f);
	return 0;
}


int myutil::writeFile(const char * data, const int num, const char * path)
{
	FILE * f = fopen(path, "wb");
	if(f == NULL)
	{
		printf("Can not open file '%s' to write.", path);
		return 1;
	}

	fwrite(data, sizeof(char), num, f);
	fclose(f);
	return 0;
}

int myutil::writeFile(const char * data, const char * path)
{
	return writeFile(data, strlen(data), path);
}
int myutil::writeFile(const string & data, const char * path)
{
	return writeFile(data.c_str(), data.size(), path);
}


#ifdef _WIN32_WINNT
/**
* Function: 字符编码转换, 仅用于win32系统
*
* Example:
*	//CP_UTF8 : utf-8
	//CP_ACP : ANSI (GBK)

	//CP_UTF8 to CP_ACP
	CodeConvert_Win(output,input.c_str(), CP_ACP ,  CP_UTF8);
*
* Params: output:转换输出的字符串; input: 需要转换的字符串, fromCodePage: input的编码格式; toCodePage: output编码格式
*	编码格式定义参考<winnls.h>
* Return: none
*
* Version: 1.0
* Author: lujun
* Time: 2012/02/07 14:13
**/
void myutil::CodeConvert_Win(string & output, const char * input, unsigned int fromCodePage, unsigned int toCodePage )
{
	int len = MultiByteToWideChar(fromCodePage, 0, input, -1, NULL, 0);// 先获取转换后的长度
	wchar_t * wcharBuf = new wchar_t[len];// 分配宽字符空间
	MultiByteToWideChar(fromCodePage, 0, input, -1, wcharBuf, len);// 转换为宽字符
	len = WideCharToMultiByte(toCodePage, 0, wcharBuf, -1, NULL, 0, NULL, NULL);// 获取目标编码格式的字符串长度
	char * charBuf = new char[len];// 分配目标编码字符串空间
	WideCharToMultiByte(toCodePage, 0, wcharBuf, -1, charBuf, len, NULL, NULL);// 转换到目标编码
	output.assign(charBuf);

	delete[] wcharBuf;
	delete[] charBuf;
}
#endif


string myutil::getMidStr(const string & str, const char * start, const char * end, int start_index)
{
	int start_len = strlen(start);

	int s = str.find(start, start_index);
	if(s == string::npos)
	{
		return string();
	}

	int e = str.find(end, s + start_len);

	if(e > s + start_len)
	{
		return str.substr(s + start_len, e - s - start_len);
	}
	return string();
}

int myutil::splitString(const char * str, vector<string> & res, const char sp)
{
	res.clear();

	string tmp = "";
	bool flag = true;
	unsigned length = strlen(str);

	for(unsigned i = 0; i < length; ++i)
	{
		unsigned char ch = str[i];
		if(ch == sp)
		{
			if(!flag)
			{
				tmp.shrink_to_fit();
				res.push_back(tmp);
				flag = true;
				tmp = "";
			}
			continue;
		}
		else
		{
			tmp.append(1, ch);
			flag = false;
		}
	}

	if(tmp.size() > 0)
	{
		tmp.shrink_to_fit();
		res.push_back(tmp);
	}
	return res.size();
}

int myutil::runCommand(string & result, const char * cmd)
{
	char tmp[1024];
	int t = time(NULL) % 1000000;
	sprintf(tmp, "%s > tmp_%d", cmd, t);

	int res = system(tmp);//执行外部命令 为了获取输出内容, 将其重定向到磁盘文件.

	sprintf(tmp, "tmp_%d", t);
	readFile(tmp, result); //读取磁盘文件
	boost::filesystem::remove(boost::filesystem::path(tmp));//删除磁盘文件
	return res;
}

int myutil::getWebPage(string url, string & res_data, const int timeOut)
{
	try
	{
		boost::trim(url);
		if(boost::starts_with(url, "http://"))
		{
			url = url.substr(7);
		}
		int uri_start_index = url.find('/', 0);
		string host;
		string uri;
		if(uri_start_index == string::npos)
		{
			host = url;
			uri = "/";
		}
		else
		{
			host = url.substr(0, uri_start_index) ;
			uri = url.substr(uri_start_index) ;
		}

		boost::asio::ip::tcp::iostream s;

		// The entire sequence of I/O operations must complete within 60 seconds.
		// If an expiry occurs, the socket is automatically closed and the stream
		// becomes bad.
		s.expires_from_now(boost::posix_time::seconds(timeOut));

		// Establish a connection to the server.
		s.connect(host, "http");
		if(!s)
		{
			std::cout << "Unable to connect: " << s.error().message() << "\n";
			return 1;
		}

		// Send the request. We specify the "Connection: close" header so that the
		// server will close the socket after transmitting the response. This will
		// allow us to treat all data up until the EOF as the content.
		s << "GET " << uri << " HTTP/1.0\r\n";
		s << "Host: " << host << "\r\n";
		s << "Accept: */*\r\n";
		s << "Accept-Language:zh,zh-CN;q=0.8,en;q=0.6,ug;q=0.4,zh-TW;q=0.2\r\n";
		s << "User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7\r\n";
		s << "Connection: close\r\n\r\n";

		// By default, the stream is tied with itself. This means that the stream
		// automatically flush the buffered output before attempting a read. It is
		// not necessary not explicitly flush the stream at this point.

		// Check that response is OK.
		std::string http_version;
		s >> http_version;
		unsigned int status_code;
		s >> status_code;
		std::string status_message;
		std::getline(s, status_message);
		if(!s || http_version.substr(0, 5) != "HTTP/")
		{
			std::cout << "Invalid response\n";
			return 1;
		}
		if(status_code != 200)
		{
			std::cout << "Response returned with status code " << status_code << "\n";
			return 1;
		}

		// Write the remaining data to output.
		std::string res((istreambuf_iterator<char>(s.rdbuf())),
		                istreambuf_iterator<char>());
		res_data.assign(res);

		return 0;
	}
	catch(std::exception & e)
	{
		std::cout << "Exception: " << e.what() << "\n";
	}
	return 1;
}
